package com.linkhub.oms.admin.modules.order.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.google.common.collect.Lists;
import com.linkhub.oms.admin.common.exception.ExceptionFactory;
import com.linkhub.oms.admin.modules.order.domain.param.orderproduct.OrderLocalSkuDeleteParam;
import com.linkhub.oms.admin.modules.order.domain.param.orderproduct.OrderLocalSkuReplaceParam;
import com.linkhub.oms.admin.modules.order.domain.param.orderproduct.OrderLocalSkuUpdateParam;
import com.linkhub.oms.admin.modules.order.service.OrderBizService;
import com.linkhub.oms.admin.modules.order.service.OrderProductBizService;
import com.linkhub.oms.common.enums.mp.OrderProductTypeEnum;
import com.linkhub.oms.common.util.CacheKeyAssist;
import com.linkhub.oms.common.util.QtStreamUtil;
import com.linkhub.oms.component.redis.locker.DistributedLocker;
import com.linkhub.oms.dao.mpservice.ILocalProductService;
import com.linkhub.oms.dao.mpservice.IOrderProductService;
import com.linkhub.oms.entity.LocalProductEntity;
import com.linkhub.oms.entity.OrderProductEntity;
import com.linkhub.oms.entity.resulttype.OrderLocalProductResultEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

import static com.linkhub.oms.common.constant.ShopifyConstant.ORDER_DATA_TYPE_KEY;

/**
 * @Description:
 * @Author: echo
 * @Date: 2024/4/6 11:25
 * @Version: 1.0
 */
@Slf4j
@Service
public class OrderProductBizServiceImpl implements OrderProductBizService {
    @Resource
    private IOrderProductService orderProductService;
    @Resource
    private DistributedLocker distributedLocker;
    @Resource
    private ILocalProductService localProductService;
    @Resource
    private OrderBizService orderBizService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveOrderLocalProduct(OrderLocalSkuUpdateParam skuUpdateParam) {
        String sysShopId = skuUpdateParam.getSysShopId();
        String sysOrderId = skuUpdateParam.getSysOrderId();
        String lockKey = CacheKeyAssist.getShopifyDataSyncLockKey(sysShopId, ORDER_DATA_TYPE_KEY);
        LocalProductEntity localProduct = localProductService.getBySkuId(skuUpdateParam.getLocalSkuId());
        if (Objects.isNull(localProduct)) {
            throw ExceptionFactory.getI18nBizException("validation.order.localSkuId.notBlank");
        }
        try {
            if (!distributedLocker.tryLock(lockKey)) {
                throw ExceptionFactory.getI18nBizException("order.sync.concurrence.error");
            }
            convertOrderLocalProductIfNecessary(sysOrderId);

            OrderProductEntity orderLocalProduct = convert(skuUpdateParam, localProduct);
            orderProductService.save(orderLocalProduct);

            orderBizService.resetOrderLogistic(sysOrderId);

        } finally {
            distributedLocker.unlock(lockKey);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateOrderLocalProduct(OrderLocalSkuUpdateParam skuUpdateParam) {
        String sysShopId = skuUpdateParam.getSysShopId();
        String sysOrderId = skuUpdateParam.getSysOrderId();
        String lockKey = CacheKeyAssist.getShopifyDataSyncLockKey(sysShopId, ORDER_DATA_TYPE_KEY);
        try {
            if (!distributedLocker.tryLock(lockKey)) {
                throw ExceptionFactory.getI18nBizException("order.sync.concurrence.error");
            }
            convertOrderLocalProductIfNecessary(sysOrderId);
            OrderProductEntity update = new OrderProductEntity();
            update.setCurrentQuantity(skuUpdateParam.getCurrentQuantity());
            orderProductService.updateOrderProduct(sysOrderId, skuUpdateParam.getLocalSkuId(), skuUpdateParam.getShopProductId(), update);
            orderBizService.resetOrderLogistic(sysOrderId);
        } finally {
            distributedLocker.unlock(lockKey);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void replaceOrderLocalProduct(OrderLocalSkuReplaceParam skuReplaceParam) {
        String sysShopId = skuReplaceParam.getSysShopId();
        String sysOrderId = skuReplaceParam.getSysOrderId();
        String lockKey = CacheKeyAssist.getShopifyDataSyncLockKey(sysShopId, ORDER_DATA_TYPE_KEY);
        try {
            if (!distributedLocker.tryLock(lockKey)) {
                throw ExceptionFactory.getI18nBizException("order.sync.concurrence.error");
            }
            convertOrderLocalProductIfNecessary(sysOrderId);

            OrderProductEntity update = new OrderProductEntity();
            update.setSkuId(skuReplaceParam.getReplaceSkuId());
            orderProductService.updateOrderProduct(sysOrderId, skuReplaceParam.getLocalSkuId(), skuReplaceParam.getShopProductId(), update);
            orderBizService.resetOrderLogistic(sysOrderId);
        } finally {
            distributedLocker.unlock(lockKey);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteOrderProduct(OrderLocalSkuDeleteParam skuDeleteParam) {
        String sysShopId = skuDeleteParam.getSysShopId();
        String sysOrderId = skuDeleteParam.getSysOrderId();
        String lockKey = CacheKeyAssist.getShopifyDataSyncLockKey(sysShopId, ORDER_DATA_TYPE_KEY);
        try {
            if (!distributedLocker.tryLock(lockKey)) {
                throw ExceptionFactory.getI18nBizException("order.sync.concurrence.error");
            }
            convertOrderLocalProductIfNecessary(sysOrderId);
            long localProductCount = orderProductService.countOrderLocalProduct(sysOrderId);
            if (localProductCount <= 1) {
                throw ExceptionFactory.getI18nBizException("order.product.delete.count.error");
            }

            orderProductService.deleteOrderLocalProduct(sysOrderId, skuDeleteParam.getLocalSkuId(), skuDeleteParam.getShopProductId());
            orderBizService.resetOrderLogistic(sysOrderId);

        } finally {
            distributedLocker.unlock(lockKey);
        }

    }

    private void convertOrderLocalProductIfNecessary(String sysOrderId) {
        if (orderProductService.existOrderLocalProduct(sysOrderId)) {
            return;
        }
        List<String> orderIds = Lists.newArrayList(sysOrderId);
        List<OrderLocalProductResultEntity> orderLocalProducts = orderProductService
                .listOrderLocalProducts(orderIds);

        List<OrderProductEntity> orderProducts = QtStreamUtil.map(orderLocalProducts,
                OrderLocalProductResultEntity::toOrderLocalProduct);
        if (CollUtil.isEmpty(orderProducts)) {
            return;
        }

        orderProductService.deleteBySysOrderIds(orderIds, OrderProductTypeEnum.THIRD_PARTY);
        orderProductService.saveBatch(orderProducts);
    }

    private OrderProductEntity convert(OrderLocalSkuUpdateParam skuUpdateParam, LocalProductEntity localProduct) {
        OrderProductEntity orderProduct = new OrderProductEntity();
        orderProduct.setSysOrderId(skuUpdateParam.getSysOrderId());
        orderProduct.setSkuId(skuUpdateParam.getLocalSkuId());
        orderProduct.setSkuTitle(localProduct.getSku());
        orderProduct.setPrice(null);
        orderProduct.setCurrentQuantity(skuUpdateParam.getCurrentQuantity());
        orderProduct.setProductType(OrderProductTypeEnum.LOCAL);
        orderProduct.setCreatedTime(LocalDateTime.now());
        orderProduct.setUpdateTime(LocalDateTime.now());
        return orderProduct;

    }
}
